/**
 * @file 文件 main.c
 * @author  作者 zcl (没什么用@瞎说.com)
 * @brief 简介：
 * @version 版本 0.1
 * @date 日期：2020-09-18
 * 
 * @copyright Copyright (c) 2020
 * 
 */
#include "main.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"
#include "i2c.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "u8g2.h"
#include "demo.h"
#include "my_sensor.h"
#include "adc.h"

// #include "mk_dht11.h"

void SystemClock_Config(void);
HAL_StatusTypeDef SensorWrite(uint16_t memaddr, uint8_t dat);
static u8g2_t u8g2;

char aa[25];

#if 1 //串口printf
#include <stdio.h>
int _write(int fd, char *ptr, int len)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)ptr, len, 0xFFFF);
  return len;
}
#endif

uint8_t status;
int16_t OX = 0;
int16_t _OX = 0;
int16_t OY = 0;
int16_t _OY = 0;
int16_t OZ = 0;
int16_t _OZ = 0;
uint8_t OO[6] = {0};
char X_value[10];
char Y_value[10];
char Z_value[10];

uint16_t ADC2_Value;

HAL_StatusTypeDef SensorWrite(uint16_t memaddr, uint8_t dat)
{
  return HAL_I2C_Mem_Write(&hi2c1, LIS3DSH_WRITE_ADDR, memaddr, 1, &dat, 1, 0xff);
}
int16_t uint2int(uint16_t i)
{
  if (i <= 32767)
  {
    return (int16_t)i;
  }
  else
  {
    return (int16_t)i - 65535;
  }
}
// region u8g2所需的回调函数
/**
 * @brief 简介：此为u8g2的复位命令或数据与延迟函数
 * 
 * @param 参数 u8x8： u8g2实例
 * @param 参数 msg： 消息
 * @param 参数 arg_int： 参数
 * @param 参数 arg_ptr：参数
 * @return  返回值uint8_t: 
 */
uint8_t u8x8_stm32_gpio_and_delay(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
{
  switch (msg)
  {
  case U8X8_MSG_GPIO_AND_DELAY_INIT:
    HAL_Delay(1);
    break;
  case U8X8_MSG_DELAY_MILLI:
    HAL_Delay(arg_int);
    break;
  case U8X8_MSG_GPIO_DC:
    HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, arg_int);
    break;
  case U8X8_MSG_GPIO_RESET:
    HAL_GPIO_WritePin(OLED_RES_GPIO_Port, OLED_RES_Pin, arg_int);
    break;
  }
  return 1;
}
/** 传输命令
 * @brief 简介：spi传输指令和片选
 * 
 * @param 参数 u8x8： 
 * @param 参数 msg： 
 * @param 参数 arg_int： 
 * @param 参数 arg_ptr： 
 * @return  返回值uint8_t: 
 */
uint8_t u8x8_byte_3Wire_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  switch (msg)
  {
  case U8X8_MSG_BYTE_SEND:
    HAL_SPI_Transmit(&hspi1, (uint8_t *)arg_ptr, arg_int, 0xff);
    break;
  case U8X8_MSG_BYTE_INIT:
    break;
  case U8X8_MSG_BYTE_SET_DC:
    HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, arg_int);
    break;
  case U8X8_MSG_BYTE_START_TRANSFER:
    HAL_GPIO_WritePin(OLED_CS_GPIO_PORT, OLED_CS_PIN, GPIO_PIN_RESET);
    break;
  case U8X8_MSG_BYTE_END_TRANSFER:
    HAL_GPIO_WritePin(OLED_CS_GPIO_PORT, OLED_CS_PIN, GPIO_PIN_SET);
    break;
  }
  return 1;
}
// endregion
int main(void)
{
  // region hal系统初始化
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_SPI1_Init();
  MX_I2C1_Init();
  MX_ADC2_Init();

  // endregion
  /*传感器初始化*/
  SensorWrite(LIS3DSH_CTRL_REG1_ADDR, 0x01); //启用SM1中断等
  SensorWrite(LIS3DSH_CTRL_REG3_ADDR, 0x48); //int1使能，低有效的中断信号，中断是电平模式而非脉冲模式，中断2禁用，中断1DRDY启用，矢量滤波不启用，无软复位位。
  SensorWrite(LIS3DSH_CTRL_REG4_ADDR, 0x47); //前四位100Hz，后三位启用三个方向的轴，中间的一位启用块更新
  SensorWrite(LIS3DSH_CTRL_REG5_ADDR, 0x00); //过滤器800Hz，刻度2G，自检关闭，spi4线模式
  SensorWrite(LIS3DSH_THRS1_1_ADDR, 0x55);   //SM1操作阈值
  SensorWrite(LIS3DSH_ST1_1_ADDR, 0x05);     //
  SensorWrite(LIS3DSH_ST1_2_ADDR, 0x11);
  SensorWrite(LIS3DSH_MASK1_B_ADDR, 0xfc); //SM1运动检测操作的轴的符号掩码（交换）XYZ轴启用正，不启用负
  SensorWrite(LIS3DSH_MASK1_A_ADDR, 0xfc); //SM1运动检测操作的轴和符号掩码（默认）XYZ轴启用正，不启用负
  SensorWrite(LIS3DSH_SETT1_ADDR, 0x01);
  /**/
  // region /*显示器初始化*/
  u8g2_Setup_ssd1306_128x64_noname_1(&u8g2, U8G2_R0, u8x8_byte_3Wire_hw_spi, u8x8_stm32_gpio_and_delay);

  u8g2_InitDisplay(&u8g2);
  u8g2_SetPowerSave(&u8g2, 0);
  u8g2_FirstPage(&u8g2);
  u8g2_ClearDisplay(&u8g2);
  u8g2_SetFont(&u8g2, u8g2_font_helvB12_tr);
  u8g2_SetDrawColor(&u8g2, 1);
  /**/
  // endregion
  while (1)
  {
    HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);

#define adc

#ifdef lis3dsh
    status = ReadStatus();
    if (status != 0)
    {
      ReadXYZ(OO);
      OX = uint2int((OO[1] << 8 | OO[0])) * 0.59814453125;
      OY = uint2int((OO[3] << 8 | OO[2])) * 0.59814453125;
      OZ = uint2int((OO[5] << 8 | OO[4])) * 0.59814453125;
    }
    siprintf(X_value, "x:%d", OX);
    siprintf(Y_value, "y:%d", OY);
    siprintf(Z_value, "z:%d", OZ);
#endif

#ifdef adc
    siprintf(X_value, "x:%d", 12);

    HAL_ADC_Start(&hadc2);
    HAL_ADC_PollForConversion(&hadc2, 50);
    if (HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc2), HAL_ADC_STATE_REG_EOC))
    {
      ADC2_Value = HAL_ADC_GetValue(&hadc2);
      siprintf(X_value, "adc:%d mv", ADC2_Value);
    }
#endif
    u8g2_FirstPage(&u8g2);
    do
    {

      u8g2_DrawRFrame(&u8g2, 1, 1, 127, 63, 10);
      u8g2_DrawStr(&u8g2, 12, 15, X_value);
      u8g2_DrawStr(&u8g2, 12, 30, Y_value);
      u8g2_DrawStr(&u8g2, 12, 48, Z_value);
    } while (u8g2_NextPage(&u8g2));
    HAL_Delay(200);
  }
}

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}
// region 绘制电池
/*** @brief 简介：画一个空的电池*/
void drawBattery(uint8_t x, uint8_t y)
{
  u8g2_DrawBox(&u8g2, x, y + 8, 3, 14);
  u8g2_DrawLine(&u8g2, x + 2, y + 1, x + 2, y + 28);
  u8g2_DrawFrame(&u8g2, x + 3, y, 54, 30);
  u8g2_DrawFrame(&u8g2, x + 4, y + 1, 52, 28);
  u8g2_DrawLine(&u8g2, x + 57, y + 1, x + 57, y + 28);
}
/**@brief 简介：填满电池 */
void drawBatteryFull(uint8_t x, uint8_t y)
{
  u8g2_DrawBox(&u8g2, x + 7, y + 4, 46, 22);
}
/*** @brief 简介：电池充电*/
void drawBatterycharging(uint8_t x, uint8_t y)
{
  uint8_t x1 = x + 18;
  uint8_t y1 = y + 5;
  u8g2_DrawTriangle(&u8g2, x1, y1 + 4, x1 + 14, y1 + 18, x1 + 15, y1 + 9);
  u8g2_DrawTriangle(&u8g2, x1 + 10, y1, x1 + 26, y1 + 15, x1 + 11, y1 + 9);
}
/*** @brief 简介：低电*/
void drawBatteryLow(uint8_t x, uint8_t y)
{
  u8g2_DrawBox(&u8g2, x + 50, y + 4, 3, 22);
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}
// endregion
#ifdef USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
